<?php
/**
 * Created by PhpStorm.
 * User: LiuJiaJun
 * Date: 2018/11/18
 * Time: 20:55
 */

namespace service\file;


class CommonFile implements File
{
    private $path;
    private $filePath;
    private $key;

    public function __construct($key, $path)
    {
        $this->key = $key;
        $this->path = $path;
        $info = pathinfo($path);
        if (empty($key)) {
            $this->filePath = CMF_ROOT . $path;
        } else {
            $this->filePath = CMF_ROOT . $info['dirname'] . '/' . $key . '/' . $info['basename'];
        }
    }


    public function read()
    {
        if (!$this->isExist()) {
            return false;
        }
        $fp = fopen($this->filePath, 'r');
        $data = fread($fp, filesize($this->filePath));
        fclose($fp);
        return $data;
    }

    public function write($data = [])
    {
        $this->initDir();
        $canWrite = false;
        if (is_array($data)) {
            $data = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        }
        if (is_object($data)) {
            $data = serialize($data);
        }
        if ($fp = fopen($this->filePath, 'w')) {
            $startTime = microtime();
            do {
                $canWrite = flock($fp, LOCK_EX);//对文件加锁
                if (!$canWrite) {
                    usleep(round(rand(0, 100) * 1000));
                }
                //超时时间设置为1ms,在这个时间内没有获得就反复获得，知道获取到权限为止
            } while ((!$canWrite) && ((microtime() - $startTime) < 1000));
        }
        if ($canWrite) {
            fwrite($fp, $data);
            flock($fp, LOCK_UN);//解锁
        }
        return fclose($fp);
    }

    public function delete()
    {
        if (!$this->isExist()) {
            return false;
        }
        return unlink($this->filePath);
    }

    /**
     * 对文件追加写入。
     *
     * @param array $data
     */
    public function appendWrite($data = [])
    {
        $oldPath = $this->filePath;
        if ($this->isExist()) {
            //找到修改文件名文件的位置
            $pos = strrpos($oldPath, '/');
            //不要修改的部分
            $base = substr($oldPath, 0, $pos);
            //文件名及后缀
            $path = substr($oldPath, $pos);

            $filenamePos = strpos($path, '.');
            $fileName = substr($path, 0, $filenamePos);
            $extName = substr($path, $filenamePos);

            $newPath = $base . $fileName . "_" . date('His', time()) . $extName;
            $this->filePath = $newPath;
        }
        $this->write($data);
        $this->filePath = $oldPath;
    }


    /**
     * 判断文件是否存在
     *
     * @return bool
     */
    public function isExist()
    {
        if (empty($this->filePath) || !file_exists($this->filePath)) {
            return false;
        }
        return true;
    }

    /**
     * 获取分割的关键字
     *
     * @return mixed
     */
    public function getKey()
    {
        return $this->key;
    }

    /**
     * 获取文件相对路径
     *
     * @return mixed
     */
    public function getPath()
    {
        return $this->path;
    }

    /**
     * 获取文件绝对路径
     *
     * @return string
     */
    public function getFilePath()
    {
        return $this->filePath;
    }

    /**
     * 处理文件夹不存在的情况
     */
    private function initDir()
    {
        $path = $this->filePath;
        $dirname = dirname($path);
        //如果文件不存在
        if (!file_exists($path)) {
            //如果文件夹不存在，创建文件夹
            if (!is_dir($dirname)) {
                mkdir($dirname, 0777, true);
            }
        }
    }

}